﻿package 
{
	import org.flixel.*;
	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import flash.display.Shape;
	import flash.filters.GlowFilter;
	
	/**
	 * The class represents the lightning bolt that gets drawn on screen.
	 */
	public class Lightning extends FlxSprite
	{
		private const MAX_SPARKS:uint = 25;
		private const TILE_WIDTH:uint = 15;
		private const TILE_HEIGHT:uint = 15;
		private const FUDGE_WIDTH:Number = 2.5;
		private const FUDGE_HEIGHT:Number = 2.5;
		
		private var _playstate:PlayState = FlxG.state as PlayState;
		private var _boltOrigin:FlxPoint;
		private var _boltTarget:FlxPoint;

		private var _radius:Number = 5;
		private var _visibleDuration:Number = 0;
		private var _visibleTimer:Number;
		private var _range:Number = 100;
		
		private var _timeFired:Number = 0;
		private var _timeHit:Number = 0;
		
		public var sparkEmitter:FlxEmitter;
		public var bulbSparkEmitter:FlxEmitter;
		
		public function Lightning()
		{
			super();
			
			_boltOrigin = new FlxPoint();
			_boltTarget = new FlxPoint();
			
			sparkEmitter = new FlxEmitter();
			sparkEmitter.setXSpeed( -50, 50);
			sparkEmitter.setYSpeed( -50, 50);
			
			for(var i:uint = 0; i < MAX_SPARKS; i++)
			{
				var s:LightningSparks = new LightningSparks();
				s.createGraphic(1, 1, generateBoltColor());
				sparkEmitter.add(s);
			}
			_playstate.add(sparkEmitter);
			
			bulbSparkEmitter = new FlxEmitter();
			bulbSparkEmitter.setXSpeed( -50, 50);
			bulbSparkEmitter.setYSpeed( -50, 50);
			
			for(i = 0; i < MAX_SPARKS; i++)
			{
				s = new LightningSparks();
				s.createGraphic(1, 1, generateSparkColor());
				bulbSparkEmitter.add(s);
			}
			_playstate.add(bulbSparkEmitter);
			
			exists = false;
		}
		
		public function get timeFired():Number
		{
			return _timeFired;
		}
		
		public function get timeHit():Number
		{
			return _timeHit;
		}
		
		public function Fire(origin:FlxPoint, target:FlxPoint):void
		{
			_boltOrigin = origin;
			_boltTarget = target;
			
			exists = true;
			_visibleTimer = _visibleDuration;
		}
		
		public function StopFiring():void
		{
			exists = false;
			PlayerGun.firing = false;
			
			for (var i:int = 0; i < _playstate.lightBulbs.members.length; i++)
			{
				var bulb:LightBulb = _playstate.lightBulbs.members[i] as LightBulb;
				
				bulb.increaseTimer.pause();
			}
		}
		
		//override public function update():void
		//{
			//if (visible)
			//{
				//_visibleTimer -= FlxG.elapsed;
				//
				//if (_visibleTimer <= 0)
				//{
					//this.kill();
				//}
			//}
			//super.update();
		//}
		
		override public function render():void
		{
			var canvas:Shape = new Shape();
			var scrollX:int = FlxG.scroll.x;
			var scrollY:int = FlxG.scroll.y;
			
			if (Math.random() < 1)
			{
				var boltColor:Number = generateBoltColor();
				var dx:int = _boltOrigin.x - _boltTarget.x;
				var dy:int = _boltOrigin.y - _boltTarget.y;
				var dist:int = int(FlxMath.sqrt(dx * dx + dy * dy));
				//var degreesAngle:Number = FlxMath.asDegrees(FlxMath.atan2(dy, dx));
				var degreesAngle:Number = FlxU.getAngle(dx, dy);
				var radiansAngle:Number = FlxMath.asRadians(degreesAngle);
				
				_timeFired += FlxG.elapsed;
				
				// Limit the gun to a set range
				if (dist > _range)
				{
					_boltTarget.x = _boltOrigin.x - int(_range * Math.cos(radiansAngle));
					_boltTarget.y = _boltOrigin.y - int(_range * Math.sin(radiansAngle));
					dist = _range;
				}
				
				var traveled:Number = _radius - 5;
				var linethickness:Number = 1;
				var alpha:Number = 1;
				
				canvas.graphics.lineStyle (linethickness, boltColor, alpha);
				canvas.graphics.moveTo (_boltOrigin.x, _boltOrigin.y);
				
				while (traveled < dist)
				{
					var speed:Number = Math.random() * 2 + _radius;
					var bx:int = traveled * Math.cos(radiansAngle);
					var by:int = traveled * Math.sin(radiansAngle);
					traveled += speed;
					var curX:Number = (_boltOrigin.x - bx) + Math.random () * _radius - _radius / 2;
					var curY:Number = (_boltOrigin.y - by) + Math.random () * _radius - _radius / 2;
					
					canvas.graphics.lineStyle (linethickness, boltColor, alpha);
					canvas.graphics.lineTo (curX, curY);
					
					// check for tilemap collision
					var tileX:uint = (curX - scrollX) / TILE_WIDTH;
					var tileY:uint = (curY - scrollY) / TILE_HEIGHT;
					
					if ((_playstate.lightningmap.getTile(tileX, tileY)) > _playstate.lightningmap.collideIndex)
					{
						sparkEmitter.x = (_boltOrigin.x > curX)?(curX - scrollX + 10):(curX - scrollX - 10);
						sparkEmitter.y = (_boltOrigin.y > curY)?(curY - scrollY):(curY - scrollY - 10);
						sparkEmitter.start(true, 3, 1);
						
						_boltTarget.x = curX;
						_boltTarget.y = curY;
						
						dx = _boltOrigin.x - _boltTarget.x;
						dy = _boltOrigin.y - _boltTarget.y;
						dist = int(FlxMath.sqrt (dx * dx + dy * dy));						
					}
					
					// check if there is a lightbulb here
					for (var i:int = 0; i < _playstate.lightBulbs.members.length; i++)
					{
						var bulb:LightBulb = _playstate.lightBulbs.members[i] as LightBulb;
						if ((bulb.onScreen()) && 
							(curX >= bulb.x + scrollX - FUDGE_WIDTH) && (curX <= bulb.x + scrollX + bulb.width + FUDGE_WIDTH) && 
							(curY >= bulb.y + scrollY - FUDGE_HEIGHT) && (curY <= bulb.y + scrollY + bulb.height + FUDGE_HEIGHT))
						{
							//collision!
							if (!bulb.isFullyPowered())
							{
								_timeHit += FlxG.elapsed;
								
								bulbSparkEmitter.x = bulb.x + bulb.width / 2;
								bulbSparkEmitter.y = bulb.y + bulb.height / 2;
								bulbSparkEmitter.start(true, 3, 1);
								
								if (bulb.currentPowerLevel == 0)
								{
									bulb.increaseTimer.start();
								}
								else
								{
									bulb.charge = bulb.currentPowerLevel * bulb.chargeSpeed;
									bulb.increaseTimer.play();
								}
							}
							
							_boltTarget.x = curX;
							_boltTarget.y = curY;
							dx = _boltOrigin.x - _boltTarget.x;
							dy = _boltOrigin.y - _boltTarget.y;
							dist = int(FlxMath.sqrt (dx * dx + dy * dy));
							break;
						}
						else
						{
							bulb.increaseTimer.pause();
						}
					}
					
					//linethickness += 1;
					//alpha += .25;
				}
				
				//canvas.graphics.lineStyle (linethickness, boltColor, alpha);
				canvas.graphics.lineStyle (linethickness, boltColor, 0);
				canvas.graphics.lineTo (_boltTarget.x , _boltTarget.y );
				canvas.graphics.endFill();
				
				var glow:GlowFilter = new GlowFilter;
				glow.color = 0xB8A9EE;
				glow.strength = 2;
				glow.blurX = 10;
				glow.blurY = 10;
				canvas.filters = [glow];
				FlxG.buffer.draw(canvas, null, null, "screen");	
				FlxG.play(SoundFiles.lightningSound, 0.125);
			}
		}
		
		private function generateBoltColor():Number
		{
			switch (Math.floor(Math.random() * 5))
			{
				case 0:
					return 0xFFD2C5FB;
				case 1:
					return 0xFFD2C3EF;
				case 2:
					return 0xFFE2DAF2;
				case 3:
					return 0xFFFBF4FC;
				case 4:
					return 0xFFFFFFFF;
				default:
					return 0xFFFFFFFF;
			}
		}
		
		private function generateSparkColor():Number
		{
			switch (Math.floor(Math.random() * 7)) 
			{
				case 0:
					return 0xFFFDFCEB;
				case 1:
					return 0xFFFBA942;
				case 2:
					return 0xFFB5851D;
				case 3:
					return 0xFF370249;
				case 4:
					return 0xFFFCECD9;
				case 5:
					return 0xFFEBECDC;
				case 6:
					return 0xFFDA9822;
				default:
					return 0xFFFFFFFF;
			}
		}
		
	}
}